package com.nowcoder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nowcoder.entity.LoginRecord;
import com.nowcoder.entity.User;
import com.nowcoder.mapper.UserMapper;
import com.nowcoder.service.LoginRecordService;
import com.nowcoder.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nowcoder.utils.MailUtil;
import com.nowcoder.utils.NowCoderUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import static com.nowcoder.utils.NowCoderConstant.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author cd
 * @since 2021-12-17
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private MailUtil mailUtil;

    @Autowired
    private TemplateEngine templateEngine;

    @Autowired
    private LoginRecordService loginRecordService;

    @Value("${nowcoder.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Override
    public User findById(int id) {
        return baseMapper.selectById(id);
    }

    @Override
    public User findByUid(String uid) {
        return baseMapper.selectOne(new QueryWrapper<User>().eq("uid", uid));
    }

    @Override
    public User selectByName(String username) {
        return baseMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    public User selectByEmail(String email) {
        return baseMapper.selectOne(new QueryWrapper<User>().eq("email", email));
    }

    @Override
    public Map<String,Object> register(User user) {
        Map<String, Object> map = new HashMap<>();

        if (user == null) throw new IllegalArgumentException("参数不能为空");
        if (StringUtils.isBlank(user.getUsername())) {
            map.put("usernameMsg", "账号不能为空");
            return map;
        }
        if (StringUtils.isBlank(user.getPassword())) {
            map.put("passwordMsg", "密码不能为空");
            return map;
        }
        if (StringUtils.isBlank(user.getEmail())) {
            map.put("emailMsg", "邮箱不能为空");
            return map;
        }
        User u = selectByName(user.getUsername());
        if (u != null) {
            map.put("usernameMsg", "该用户名已存在");
            return map;
        }
        u = selectByEmail(user.getEmail());
        if (u != null) {
            map.put("emailMsg", "该邮箱已被注册");
            return map;
        }
        //--------------注册用户开始---------------
        user.setUid(NowCoderUtil.generateUUID());
        user.setSalt(NowCoderUtil.generateUUID().substring(0, 6));
        user.setPassword(NowCoderUtil.md5(user.getPassword() + user.getSalt()));
        user.setType(1);//普通用户
        user.setStatus(0);//未激活
        user.setActivationCode(NowCoderUtil.generateUUID());//生成激活码
        user.setAvatar(String.format("http://images.nowcoder.com/head/%dt.png",
                new Random().nextInt(100)));

        baseMapper.insert(user);

        //--------------激活邮件-----------------
        Context context = new Context();
        context.setVariable("email", user.getEmail());
        String url = domain + contextPath + "/activation/" +
                user.getUid() + "/" + user.getActivationCode();
        context.setVariable("url", url);
        String content = templateEngine.process("/mail/activation", context);
        mailUtil.sendMail(user.getEmail(), "激活账号", content);

        return map;
    }

    @Override
    public int activation(String uid, String code) {
        User user = baseMapper.selectOne(new QueryWrapper<User>().eq("uid", uid));
        if (user.getStatus() == 1) return ACTIVATION_REPEAT;
        else if (user.getActivationCode().equals(code)) {
            baseMapper.update(null, new UpdateWrapper<User>().eq("uid", uid).set("status", 1));
            clearCache(uid);
            return ACTIVATION_SUCCESS;
        } else {
            return ACTIVATION_FAILED;
        }
    }

    @Override
    public Map<String,Object> login(String username, String password, int expireSeconds) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isBlank(username)) {
            map.put("usernameMsg", "账号不能为空");
            return map;
        }
        if (StringUtils.isBlank(password)) {
            map.put("passwordMsg", "密码不能为空");
            return map;
        }
        User user = selectByName(username);
        if (user == null) {
            map.put("usernameMsg", "该账户不存在");
            return map;
        }
        if (user.getStatus() == 0) {
            map.put("usernameMsg", "该账户未激活");
            return map;
        }
        password = NowCoderUtil.md5(password + user.getSalt());
        if (!user.getPassword().equals(password)) {
            map.put("passwordMsg", "密码不正确");
            return map;
        }

        //生成登录凭证
        LoginRecord loginRecord = new LoginRecord();
        loginRecord.setUid(user.getUid());
        loginRecord.setToken(NowCoderUtil.generateUUID());
        loginRecord.setStatus(0);
        loginRecord.setExpirtion(new Date(System.currentTimeMillis() + 1000 * 60 * 10));
        loginRecord.setIp("127.0.0.1");
        loginRecord.setLoginTime(new Date());
        loginRecord.setLastTime(new Date());

        loginRecordService.oneLoginRecord(loginRecord);
        map.put("token", loginRecord.getToken());

        return map;
    }

    @Override
    public void logout(String token) {
        loginRecordService.updateTokenStatus(token, 1);
    }

    @Override
    public Map<String, Object> resetPassword(String email, String password) {
        HashMap<String, Object> map = new HashMap<>();

        // 空值处理
        if (StringUtils.isBlank(email)) {
            map.put("emailMsg", "邮箱不能为空!");
            return map;
        }
        if (StringUtils.isBlank(password)) {
            map.put("passwordMsg", "密码不能为空!");
            return map;
        }

        User user = baseMapper.selectOne(new QueryWrapper<User>().eq("email", email));
        if (user == null) {
            map.put("emailMsg", "该邮箱尚未注册!");
            return map;
        }

        password = NowCoderUtil.md5(password + user.getSalt());
        baseMapper.update(null,
                new UpdateWrapper<User>()
                        .eq("email", email)
                        .set("password", password)
                        .set("update_time", new Date()));

        map.put("user", user);

        return map;
    }

    @Override
    public LoginRecord findLoginToken(String token) {
        return loginRecordService.selectByToken(token);
    }

    @Override
    public int updateAvatar(String uid, String avatar) {
        return baseMapper.update(null,
                new UpdateWrapper<User>()
                .eq("uid", uid)
                .set("avatar", avatar));
    }

    @Override
    public Map<String, Object> updatePassword(String uid, String oldPassword, String newPassword) {
        HashMap<String, Object> map = new HashMap<>();

        if (StringUtils.isBlank(oldPassword)) {
            map.put("oldPasswordMsg", "原密码不能为空");
            return map;
        }
        if (StringUtils.isBlank(newPassword)) {
            map.put("newPasswordMsg", "新密码不能为空");
            return map;
        }

        User user = baseMapper.selectOne(new QueryWrapper<User>().eq("uid", uid));
        oldPassword = NowCoderUtil.md5(oldPassword + user.getSalt());
        if (!user.getPassword().equals(oldPassword)) {
            map.put("oldPasswordMsg", "原密码错误");
            return map;
        }

        newPassword = NowCoderUtil.md5(newPassword + user.getSalt());
        baseMapper.update(null,
                new UpdateWrapper<User>()
                        .eq("uid", uid)
                        .set("password", newPassword)
                        .set("update_time", new Date()));

        return map;
    }

    private void clearCache(String uid) {
    }


}
